/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.wsonrpc.json.support.gson;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.apexes.wsonrpc.json.JsonRpcError;
import net.apexes.wsonrpc.json.JsonRpcErrorCause;
import net.apexes.wsonrpc.json.JsonRpcResponse;

import java.lang.reflect.Type;

/**
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 */
class GsonJsonRpcResponse implements JsonRpcResponse {

    private final Gson gson;
    private final JsonObject jsonObject;
    private final String id;
    private final JsonElement result;
    private final JsonRpcError error;

    GsonJsonRpcResponse(Gson gson, JsonObject jsonObject) {
        this.gson = gson;
        this.jsonObject = jsonObject;

        if (jsonObject.has("id")) {
            JsonElement element = jsonObject.get("id");
            if (element.isJsonNull()) {
                this.id = null;
            } else {
                this.id = element.getAsString();
            }
        } else {
            this.id = null;
        }
        if (jsonObject.has("result")) {
            this.result = jsonObject.get("result");
            this.error = null;
        } else {
            JsonObject errorObject = jsonObject.getAsJsonObject("error");
            int code = errorObject.get("code").getAsInt();
            String message = null;
            JsonRpcErrorCause data = null;
            if (errorObject.has("message")) {
                JsonElement element = errorObject.get("message");
                if (!element.isJsonNull()) {
                    message = element.getAsString();
                }
            }
            if (errorObject.has("data")) {
                JsonObject dataJsonObject = errorObject.getAsJsonObject("data");
                if (!dataJsonObject.isJsonNull()) {
                    data = gson.fromJson(dataJsonObject, JsonRpcErrorCause.class);
                }
            }
            this.result = null;
            this.error = new JsonRpcError(code, message, data);
        }
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public Object getResult() {
        return result;
    }

    @Override
    public Object getResultValue(Type type) {
        if (result == null) {
            return null;
        }
        return gson.fromJson(result, type);
    }

    @Override
    public String getResultAsJson() {
        return gson.toJson(result);
    }

    @Override
    public JsonRpcError getError() {
        return error;
    }

    @Override
    public String toJson() {
        return gson.toJson(jsonObject);
    }

    @Override
    public boolean isRequest() {
        return false;
    }

    @Override
    public boolean isResponse() {
        return true;
    }
}
